package com.wqiuqiu.gulimall.product.service.impl;

import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.fastjson.TypeReference;
import com.alibaba.fastjson.serializer.BigDecimalCodec;
import com.wqiuqiu.common.R;
import com.wqiuqiu.common.excption.BizCodeEnume;
import com.wqiuqiu.gulimall.product.entity.*;
import com.wqiuqiu.gulimall.product.feign.SecdKillFeignService;
import com.wqiuqiu.gulimall.product.service.*;
import com.wqiuqiu.gulimall.product.vo.*;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.wqiuqiu.common.PageUtils;
import com.wqiuqiu.common.Query;

import com.wqiuqiu.gulimall.product.dao.SkuInfoDao;


@Service("skuInfoService")
public class SkuInfoServiceImpl extends ServiceImpl<SkuInfoDao, SkuInfoEntity> implements SkuInfoService {

    @Autowired
    SkuSaleAttrValueService skuSaleAttrValueService;
    @Autowired
    SkuImagesService skuImagesService;

    @Autowired
    SpuInfoDescService spuInfoDescService;
    @Autowired
    ProductAttrValueService productAttrValueService;
    @Autowired
    AttrAttrgroupRelationService attrAttrgroupRelationService;
    @Autowired
    AttrGroupService attrGroupService;

    @Autowired
    SpuInfoService spuInfoService;
    @Autowired
    ThreadPoolExecutor executor;
    @Autowired
    SecdKillFeignService secdKillFeignService;

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        QueryWrapper<SkuInfoEntity> wrapper = new QueryWrapper<>();
        String key = (String) params.get("key");
        String catelogId = (String) params.get("catelogId");
        String brandId = (String) params.get("brandId");
        String min = (String) params.get("min");
        String max = (String) params.get("max");

        if (!StringUtils.isEmpty(catelogId) && !catelogId.equals("0")) {
            wrapper.eq("catalog_id", catelogId);
        }
        if (!StringUtils.isEmpty(brandId) && !brandId.equals("0")) {
            wrapper.eq("brand_id", brandId);
        }
        if (!StringUtils.isEmpty(min)) {
            wrapper.ge("price", min);
        }
        if (!StringUtils.isEmpty(max)) {
            int val = Integer.parseInt(max);
            if (val > 0) {
                BigDecimal bigDecimal = new BigDecimal(val);
                wrapper.le("price", bigDecimal);
            }
        }
        if (StringUtils.isNotEmpty(key)) {
            wrapper.and(obj -> obj.eq("sku_id", key).or().like("sku_name", key));
        }

        IPage<SkuInfoEntity> page = this.page(
                new Query<SkuInfoEntity>().getPage(params),
                wrapper
        );

        return new PageUtils(page);
    }

    public SkuItemDetailVo itemBlockHandler(Long skuId, BlockException e){
        log.error(BizCodeEnume.TOO_MANY_REQUSET_EXCEPTION.getMessage());
        return null;
    }

    /**
     * 根据skuId查找信息
     * 异步执行
     * 对频繁多次访问进行限流
     * @param skuId
     * @return
     */
    @Override
    @SentinelResource(value = "getItemDetail",blockHandler = "itemBlockHandler")
    public SkuItemDetailVo item(Long skuId) throws ExecutionException, InterruptedException {
        SkuItemDetailVo skuItemDetailVo = new SkuItemDetailVo();

        //spu的基本信息
        CompletableFuture<SkuInfoEntity> skuInfoFuture = CompletableFuture.supplyAsync(() -> {
            SkuInfoEntity infoEntity = this.getById(skuId);
            skuItemDetailVo.setInfo(infoEntity);
            return infoEntity;
        }, executor);

        //异步 spu的全部销售属性
        CompletableFuture<Void> saleAttrFuture = skuInfoFuture.thenAcceptAsync((res) -> {
            List<AttrNoId> attrNoIds = findSpuAllSkusSaleAttrsBySpuId(res.getSpuId());
            skuItemDetailVo.setAttrs(attrNoIds);
        }, executor);

        //异步 spu的基本属性
        CompletableFuture<Void> baseAttrFuture = skuInfoFuture.thenAcceptAsync((res) -> {
            skuItemDetailVo.setSpuInfoDesc(spuInfoDescService.getById(res.getSpuId()));
            List<SpuItemAttrGroupVo> spuItemAttrGroupVos = this.findAttrGroupAttrs(res.getSpuId(), res.getCatalogId());
            skuItemDetailVo.setGroupAttrs(spuItemAttrGroupVos);
        }, executor);

        //同步 获取sku的图片
        CompletableFuture<Void> imageFuture = CompletableFuture.runAsync(() -> {
            List<SkuImagesEntity> imagesEntities = skuImagesService.list(new QueryWrapper<SkuImagesEntity>()
                    .eq("sku_id", skuId).isNotNull("img_url"));
            skuItemDetailVo.setImages(imagesEntities);
        }, executor);

        //获取商品的秒杀信息
        CompletableFuture<Void> secdKillFuture = CompletableFuture.runAsync(() -> {
            R r = secdKillFeignService.getSecdKillInfoBySkuId(skuId);
            if (r.getCode() ==0 ){
                SecdKillRedisVo data = r.getData(new TypeReference<SecdKillRedisVo>() {
                });
                if (data != null){
                    long now = new Date().getTime();
                    if (now >= data.getStartTime() && now <= data.getEndTime()){
                        //处于秒杀时间
                        String randCode = data.getRandCode();
                        skuItemDetailVo.setRandCode(randCode);
                        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                        String formattedDate = sdf.format(new Date(data.getEndTime()));
                        skuItemDetailVo.setEndTime(formattedDate);
                        skuItemDetailVo.setKillPrice(data.getSecdKillSkusVo().getSeckillPrice());
                        skuItemDetailVo.setIsKill(true);
                        skuItemDetailVo.setSessionId(data.getSecdKillSkusVo().getPromotionSessionId());

                    }else if (now < data.getStartTime()){
                        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                        String formattedDate = sdf.format(new Date(data.getStartTime()));
                        skuItemDetailVo.setStartTime(formattedDate);
                        skuItemDetailVo.setKillPrice(data.getSecdKillSkusVo().getSeckillPrice());
                        skuItemDetailVo.setIsKill(false);
                    }
                }
            }
        }, executor);

        CompletableFuture.allOf(imageFuture,baseAttrFuture,saleAttrFuture,secdKillFuture).get();

        return skuItemDetailVo;

    }

    @Override
    public List<SkuInfoEntity> batchInfobyIds(List<Long> skuIds) {
        return this.list(new QueryWrapper<SkuInfoEntity>().in("sku_id", skuIds));
    }


    private List<SpuItemAttrGroupVo> findAttrGroupAttrs(Long spuId, Long catalogId) {
//        //1.根据skuId找到全部的属性  连表
//        List<ProductAttrValueEntity> attrValueEntities = productAttrValueService.list(new QueryWrapper<ProductAttrValueEntity>().eq("sku_id", skuId));
//        List<Long> attrIds = attrValueEntities.stream().map(ProductAttrValueEntity::getAttrId).collect(Collectors.toList());
//        //2.根据id找到所属组id
//        List<GroupAttrsVo> spuItemAttrGroupVos = attrAttrgroupRelationService.findGroupByAttrIds(attrIds);
//        List<Long> groupIds = new ArrayList<>();
//        List<String> attrIdStrs = new ArrayList<>();
//        for (GroupAttrsVo vo : spuItemAttrGroupVos) {
//            groupIds.add(vo.getAttrGroupId());
//            attrIdStrs.add(vo.getAttrIds());
//        }
//        //查询数据库，不全组名和属性值
//        if (groupIds.size() == attrIdStrs.size()){
//
//            List<AttrGroupEntity> groupEntities = attrGroupService.list(new QueryWrapper<AttrGroupEntity>().in("attr_group_id", groupIds));
//
//
//            for (int i = 0; i < groupIds.size(); i++) {
//                if (groupIds.get(i) != null){
//
//                }
//            }
//
//
//            //根据组id找到组属性
//            spuItemAttrGroupVos.stream().map(obj->{
//                SpuItemAttrGroupVo item = new SpuItemAttrGroupVo();
//                item.setAttrGroupName();
//                item.setAtts();
//            })
//        }

        //用分类来查属性分组  连表查询
        //pms_attr_group 查到分类下的全部属性分组id，name
        List<AttrGroupEntity> catelog_id = attrGroupService.list(new QueryWrapper<AttrGroupEntity>().eq("catelog_id", catalogId));
        List<SpuItemAttrGroupVo> collect = catelog_id.stream().map(obj -> {

            SpuItemAttrGroupVo vo = new SpuItemAttrGroupVo();
            vo.setAttrGroupName(obj.getAttrGroupName());
            List<AttrNoId> attrNoIds = new ArrayList<>();
            //分组下的全部属性id
            List<AttrAttrgroupRelationEntity> attr_group_id = attrAttrgroupRelationService.list(new QueryWrapper<AttrAttrgroupRelationEntity>()
                    .eq("attr_group_id", obj.getAttrGroupId()));
            List<Long> attrIds = attr_group_id.stream().map(AttrAttrgroupRelationEntity::getAttrId).collect(Collectors.toList());
            //pms_product_attr_value 找到属性值
            List<ProductAttrValueEntity> attr_id = productAttrValueService.list(new QueryWrapper<ProductAttrValueEntity>()
                    .in("attr_id", attrIds).eq("spu_id", spuId));
            for (ProductAttrValueEntity attrValueEntity : attr_id) {
                AttrNoId attrNoId = new AttrNoId();
                attrNoId.setAttrName(attrValueEntity.getAttrName());
                attrNoId.setAttrValues(attrValueEntity.getAttrValue());
                attrNoIds.add(attrNoId);
            }
            vo.setAtts(attrNoIds);
            return vo;
        }).collect(Collectors.toList());
        return collect;
    }

    public void test() {
        List<SpuItemAttrGroupVo> attrGroupAttrs = findAttrGroupAttrs(11L, 225L);
        System.out.println(attrGroupAttrs.toString());
    }

    private List<AttrNoId> findSpuAllSkusSaleAttrsBySpuId(Long spuId) {
        //得到spu下的全部sku
        List<SkuInfoEntity> skuInfoEntities = this.list(new QueryWrapper<SkuInfoEntity>().eq("spu_id", spuId));
        List<Long> skuIds = skuInfoEntities.stream().map(SkuInfoEntity::getSkuId).collect(Collectors.toList());
        List<AttrNoId> attrNoIds = skuSaleAttrValueService.getAttrNameAndAttrValueBySkuIds(skuIds);
        return attrNoIds;
    }

}